 1.继承之继承的概念
   
   Scala中继承类的方式和Java一样，也是使用extends关键字：

class Employee extends Person{
    var salary=1000
}

   和Java一样，可在定义中给出子类需要而父类没有的字段和方法，或者重写父类的方法。

//Person类
class Person(name:String,age:Int)
//Student继承Person类
class Student(name:String,age:Int,var studentNo:String) extends Person(name,age) 

object Demo{
  def main(args: Array[String]): Unit = {
    val student=new Student("john",18,"1024")
	student.stuNo="1002"
    println(student.stuNo)
  }
}

   上面继承部分的代码等效于下面的Java代码

//Person类
class Person{
    private String name;
    private int age;
    public Person(String name,int age){
       this.name=name;
       this.age=age;
    }
}
//Student继承Person类
class Student extends Person{
    private String studentNo;
    public Student(string name,int age,String studentNo){
        super(name,age);
        this.sutdentNo=studentNo;
    }
}

 2.构造器的执行顺序
   
   Scala在继承的时候构造器的执行顺序：首先执行父类的主构造器，其次执行子类自身的主构造器。
   类有一个主构造器和任意数量的辅助构造器，而每个辅助构造器都必须以对先前定义的辅助构造器或主
构造器的调用开始。
   
   子类的辅助构造器最终都会调用主构造器。只有主构造器可以调用父类的构造器。

//Person类
class Person(name:String,age:Int){
  println("这是父类Person")
}
//Student继承Person类
class Student(name:String,age:Int,studentNo:String) extends Person(name,age){
  println("这是子类Student")
}
object Demo{
  def main(args: Array[String]): Unit = {
  //下面的语句执行时会打印下列内容:
  //这是父类Person
  //这是子类Student
  //也就是说，构造Student对象之前，首先会调用Person的主构造器
  val student=new Student("john",18,"1024")
  }
}

 3.override方法重写
   
   方法重写指的是当子类继承父类的时候，从父类继承过来的方法不能满足子类的需要，子类希望有自己
的实现，这时需要对父类的方法进行重写，方法重写是实现多态的关键。
   
   Scala中的方法重写同Java一样，也是利用override关键字标识重写父类的方法。
   
class Programmer(name:String,age:Int){
  def coding():Unit=println("我在写代码...")
}
//ScalaProgrammer继承Programmer类
class ScalaProgrammer(name:String,age:Int,workNo:String) extends Programmer(name,age){
  override def coding():Unit={
    //调用父类的方法
    super.coding()
    //增加了自己的实现
    println("我在写Scala代码...")
  }
}

object ExtendsDemo {
  def main(args: Array[String]): Unit = {
  val scalaProgrammer=new ScalaProgrammer("张三",30,"1001")
  scalaProgrammer.coding()
  }
}

   //代码运行输出内容:
   我在写代码...
   我在写Scala代码...
   
   需要强调一点：如果父类是抽象类，则override关键字可以不加。如果继承的父类是抽象类（假设抽象
类为AbstractClass，子类为SubClass），在SubClass类中，AbstractClass对应的抽象方法如果没有实
现的话，那SubClass也必须定义为抽象类，否则的话必须要有方法的实现。

//抽象的Person类
abstract class Person(name:String,age:Int){
  def walk():Unit
}
//Student继承抽象Person类
class Student(name:String,age:Int,var studentNo:String) extends Person(name,age) {
  //重写抽象类中的walk方法，可以不加override关键字
  def walk():Unit={
    println("walk like a elegant swan")
  }
}

object Demo{
  def main(args: Array[String]): Unit = {
    val stu=new Student("john",18,"1024")
    stu.walk()
  }
}

 4.类型检查与转换
   
   要测试某个对象是否属于某个给定的类，可以用isInstanceOf方法。如果测试成功，可以用
asInstanceOf方法进行类型转换。

if(p.isInstanceOf[Employee]){
   //s的类型转换为Employee
   val s = p.asInstanceOf[Employee]
}

   如果p指向的是Employee类及其子类的对象，则p.isInstanceOf[Employee]将会成功。
   如果p是null，则p.isInstanceOf[Employee]将返回false，且p.asInstanceOf[Employee]将返回null。
   如果p不是一个Employee，则p.asInstanceOf[Employee]将抛出异常。
   如果想要测试p指向的是一个Employee对象但又不是其子类，可以用：

if(p.getClass == classOf[Employee])
   
   classOf方法定义在scala.Preder对象中，因此会被自动引入。
   不过，与类型检查和转换相比，模式匹配通常是更好的选择。

p match{
    //将s作为Employee处理
    case s: Employee => ...
    //p不是Employee的情况
    case _ => ....
}